package org.example.framework.util;

import com.google.gson.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

public final class JsonUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class);
    private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();

    private JsonUtil() {
    }

    /**
     * 对象转JSON字符串, 底层使用GSON实现, 封装丰富定位信息
     *
     * @param object Java对象
     * @return JSON字符串
     */
    public static String toJson(Object object) {
        Objects.requireNonNull(object);
        try {
            return GSON.toJson(object);
        } catch (JsonIOException e) {
            LOGGER.error("unable to serialize" + object.getClass().getCanonicalName() + "to json");
            throw e;
        }
    }

    /**
     * JSON字符串转换为Java对象
     *
     * @param json  JSON字符串
     * @param clazz 类
     * @param <T>   JavaBean类型
     * @return JavaBean
     */
    public static <T> T fromJson(String json, Class<T> clazz) {
        Objects.requireNonNull(json);
        try {
            return GSON.fromJson(json, clazz);
        } catch (JsonSyntaxException e) {
            LOGGER.error("unable to parse json to " + clazz.getCanonicalName());
            throw e;
        }
    }

    /**
     * JsonElement转换为Java对象
     *
     * @param jElement JsonElement
     * @param clazz    类
     * @param <T>      JavaBean类型
     * @return JavaBean
     */
    public static <T> T fromJson(JsonElement jElement, Class<T> clazz) {
        Objects.requireNonNull(jElement);
        try {
            return GSON.fromJson(jElement, clazz);
        } catch (JsonSyntaxException e) {
            LOGGER.error("unable to parse json to " + clazz.getCanonicalName());
            throw e;
        }
    }

    /**
     * 提取JsonObject中的String字段
     *
     * @param jObject jsonObject
     * @param field   字段名
     * @return 字段值
     */
    public static String getString(JsonObject jObject, String field) {
        Objects.requireNonNull(jObject);
        if (!jObject.has(field)) {
            return "";
        }
        Object value = jObject.get(field);
        if (Objects.isNull(value)) {
            LOGGER.warn("filed {} is null", field);
            return "";
        }

        return jObject.get(field).isJsonNull() ? "" : jObject.get(field).getAsString();
    }

    /**
     * 提取JsonObject中的int字段
     *
     * @param jObject jsonObject
     * @param field   字段名
     * @return 字段值
     */
    public static int getInt(JsonObject jObject, String field) {
        Objects.requireNonNull(jObject);
        if (!jObject.has(field)) {
            return -1;
        }
        Object value = jObject.get(field);
        if (Objects.isNull(value)) {
            LOGGER.warn("filed {} is null", field);
            return -1;
        }

        return jObject.get(field).isJsonNull() ? -1 : jObject.get(field).getAsInt();
    }

    /**
     * 提取JsonObject中的Json数组
     *
     * @param jObject jsonObject
     * @param field   字段名
     * @return Json数组
     */
    public static JsonArray getJsonArray(JsonObject jObject, String field) {
        Objects.requireNonNull(jObject);

        if (!jObject.has(field)) {
            return new JsonArray();
        }
        Object value = jObject.get(field);
        if (Objects.isNull(value)) {
            LOGGER.warn("filed {} is null", field);
            return new JsonArray();
        }

        return jObject.get(field).isJsonNull() ? new JsonArray() : jObject.get(field).getAsJsonArray();
    }

    /**
     * 提取JsonObject中的boolean字段
     *
     * @param jObject jsonObject
     * @param field   字段名
     * @return 字段值
     */
    public static boolean getBoolean(JsonObject jObject, String field) {
        Objects.requireNonNull(jObject);
        if (!jObject.has(field)) {
            return false;
        }
        Object value = jObject.get(field);
        if (Objects.isNull(value)) {
            LOGGER.warn("filed {} is null", field);
            return false;
        }

        return !jObject.get(field).isJsonNull() && jObject.get(field).getAsBoolean();
    }

    /**
     * 提取JsonObject中的boolean字段
     *
     * @param jObject jsonObject
     * @param field   字段名
     * @return 字段值
     */
    public static double getDouble(JsonObject jObject, String field) {
        Objects.requireNonNull(jObject);
        if (!jObject.has(field)) {
            return 0.0d;
        }
        Object value = jObject.get(field);
        if (Objects.isNull(value)) {
            LOGGER.warn("filed {} is null", field);
            return 0.0d;
        }

        return jObject.get(field).isJsonNull() ? 0.0d : jObject.get(field).getAsDouble();
    }
}
